#include "StdAfx.h"
#include "UIListSelector.h"

UIListSelector::UIListSelector()
: m_nOriginal(0), m_pState(NULL)
{
	m_nLastTarget = 0;
}

UIListSelector::~UIListSelector(void)
{
}

void UIListSelector::EnterState( ASSISTMODE assisMode, PRESSMODE pressMode )
{
	CStateFactory::ReleaseState(m_pState);

	m_pState = CStateFactory::CreateState(assisMode, pressMode);
	m_pState->SetOwner(this);
}

void UIListSelector::Select(int nHit)
{
	INT_LIST listUnSelect;
	INT_LIST listOld = m_listSelected;
	m_pState->Select(nHit, &m_listSelected);
	
	set_difference(listOld.begin(), listOld.end(),
		m_listSelected.begin(), m_listSelected.end(), back_inserter(listUnSelect));

	for(INTLISTITER it = listUnSelect.begin();
	it != listUnSelect.end(); it++)
	{
		m_pHost->CascadeUnSelect(*it);
	}

	INT_LIST listCascadeNotify;
	for(INTLISTITER it = m_listSelected.begin();
		it != m_listSelected.end(); it++)
	{
		m_pHost->CascadeSelect(*it);
		listCascadeNotify.push_back(*it);
	}

	m_pHost->CascadeNotify(listCascadeNotify);


	

}

int UIListSelector::GetOriginal()
{
	return m_nOriginal;
}

void UIListSelector::SetOriginal( int nOriginal )
{
	m_nOriginal = nOriginal;
}

int UIListSelector::GetEnd()
{
	return m_pHost->GetSelectableCount() - 1;
}

void UIListSelector::SetHost( IHost* pHost )
{
	m_pHost = pHost;
}

INT_LIST UIListSelector::GetSelectedItems()
{
	return m_listSelected;
}

void UIListSelector::RemoveAt( int nIndex )
{
	INTLISTITER it = find(m_listSelected.begin(), m_listSelected.end(), nIndex);
	if(it != m_listSelected.end())
	{
		m_listSelected.erase(it);
	}
}

void UIListSelector::Clear()
{
	m_listSelected.clear();
}

void UIListSelector::SetLastTarget( int nLastTarget )
{
	m_nLastTarget = nLastTarget;
}

int UIListSelector::GetLastTarget()
{
	return m_nLastTarget;
}



int CKeyBoardAssist::GetTarget( int nOriginal, int nLastTarget, int nEnd, int nHit )
{
	int nTarget = 0;
	switch(nHit)
	{
	case VK_UP:
		{
			if(nLastTarget > 0)
			{
				nTarget = nLastTarget - 1;
			}
			else
			{
				nTarget = 0;
			}
		}break;
	case VK_DOWN:
		{
			if(nLastTarget < nEnd)
			{
				nTarget = nLastTarget + 1;
			}
			else
			{
				nTarget = nEnd;
			}
		}break;
	case VK_HOME:
		{
			nTarget = 0;
		}break;
	case VK_END:
		{
			nTarget = nEnd;
		}break;
	}
	
	return nTarget;
}

int CMouseAssist::GetTarget( int nOriginal, int nLastTarget, int nEnd, int nHit )
{
	return nHit;
}

void CNoPress::Handle( int* pOriginal, int nTarget, PINT_LIST pListSelected )
{
	if(NULL == pOriginal || NULL == pListSelected )
	{
		ASSERT(FALSE);
		return;
	}

	pListSelected->clear();
	pListSelected->push_back(nTarget);

	*pOriginal = nTarget;
}

void CCtrl::Handle( int* pOriginal, int nTarget, PINT_LIST pListSelected )
{
	if(NULL == pOriginal || NULL == pListSelected )
	{
		ASSERT(FALSE);
		return;
	}

	INTLISTITER it = find(pListSelected->begin(), pListSelected->end(), nTarget);

	if(it == pListSelected->end())
	{
		pListSelected->push_back(nTarget);
	}
	else
	{
		pListSelected->erase(it);
	}

	pListSelected->sort();

	*pOriginal = nTarget;
}

void CShift::Handle( int* pOriginal, int nTarget, PINT_LIST pListSelected )
{
	if(NULL == pOriginal || NULL == pListSelected )
	{
		ASSERT(FALSE);
		return;
	}

	pListSelected->clear();

	int nFrom = *pOriginal;
	int nTo   = nTarget;
	if(nFrom > nTo)
	{
		swap(nFrom, nTo);
	}

	for(int i = nFrom; i <= nTo; i++)
	{
		pListSelected->push_back(i);
	}

}

void CCtrlShift::Handle( int* pOriginal, int nTarget, PINT_LIST pListSelected )
{
	if(NULL == pOriginal || NULL == pListSelected )
	{
		ASSERT(FALSE);
		return;
	}

	INT_LIST listOriginalSelected;
	INT_LIST listCurrentSelected;

	copy(pListSelected->begin(), 
		pListSelected->end(), 
		back_inserter(listOriginalSelected));

	pListSelected->clear();

	int nFrom = *pOriginal;
	int nTo   = nTarget;
	if(nFrom > nTo)
	{
		swap(nFrom, nTo);
	}

	for(int i = nFrom; i <= nTo; i++)
	{
		listCurrentSelected.push_back(i);
	}

	set_union(listCurrentSelected.begin(), listCurrentSelected.end(),
		listOriginalSelected.begin(), listOriginalSelected.end(),
		back_inserter(*pListSelected));
}

IState* CStateFactory::CreateState( ASSISTMODE AssistMode, PRESSMODE PressMode )
{
	IState* pState = NULL;

	switch(AssistMode | PressMode)
	{
	case NoPress | KeyBoard :
		{
			pState = new CState<CNoPress, CKeyBoardAssist>();
		}break;
	case NoPress | Mouse :
		{
			pState = new CState<CNoPress, CMouseAssist>();
		}break;
	case Ctrl | KeyBoard :
		{
			pState = new CState<CCtrl, CKeyBoardAssist>();
		}break;
	case Ctrl | Mouse :
		{
			pState = new CState<CCtrl, CMouseAssist>();
		}break;
	case Shift | KeyBoard :
		{
			pState = new CState<CShift, CKeyBoardAssist>();
		}break;
	case Shift | Mouse :
		{
			pState = new CState<CShift, CMouseAssist>();
		}break;
	case CtrlShift | KeyBoard :
		{
			pState = new CState<CCtrlShift, CKeyBoardAssist>();
		}break;
	case CtrlShift | Mouse :
		{
			pState = new CState<CCtrlShift, CMouseAssist>();
		}break;

	default:
		{
		}
		
	}

	return pState;
}

void CStateFactory::ReleaseState( IState* pState )
{
	if(pState != NULL)
	{
		delete pState;
		pState = NULL;
	}
}
